//
//  JSQConversationViewController.m
//  Conversation
//
//  Created by C_HAO on 15/9/29.
//  Copyright © 2015年 CHAOO. All rights reserved.
//

#import "JSQConversationViewController.h"
#import "JSQMapViewController.h"
#import "JSQMapLocation.h"
#import "JSQShowImageViewController.h"
#import "MWPhotoBrowser.h"
#import <AssetsLibrary/AssetsLibrary.h>


@interface JSQConversationViewController () <JSQShowImageViewControllerDelegate, UINavigationControllerDelegate, UIImagePickerControllerDelegate, JSQMapViewControllerDelegate, UIActionSheetDelegate, MWPhotoBrowserDelegate>

@property (nonatomic, weak) MWPhotoBrowser *photoBrowser;
@property (nonatomic, strong) NSMutableArray *photos;
@property (nonatomic, strong) NSMutableArray *thumbs;
@property (nonatomic, strong) NSMutableArray *assets;
@property (nonatomic, strong) NSMutableArray *selections;
@property (nonatomic, strong) ALAssetsLibrary *ALAssetsLibrary;
@property (nonatomic, assign) BOOL restore;



@end

@implementation JSQConversationViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    /**
     *  You MUST set your senderId and display name
     */
    if (!self.messageData) {
        self.messageData = [[JSQChatMessageData alloc] init];
    }


    [self.collectionView addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew context:nil];
    
    [self scrollToBottomAnimated:YES];
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    if (self.delegateModal) {
        self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemStop
                                                                                              target:self
                                                                                              action:@selector(closePressed:)];
    }
}

- (void)refreshNewMessage {
    if (self.collectionView.contentOffset.y > 100) {
        self.unreadMessagesView.hidden = NO;
    } else {
        self.unreadMessagesView.hidden = YES;
        [self scrollToBottomAnimated:YES];
        [self finishReceivingMessageAnimated:YES];
    }
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    if (self.showLoadEarlierMessagesHeader) {
        if ([keyPath isEqualToString:@"contentOffset"]) {
            CGPoint offset = [change[NSKeyValueChangeNewKey] CGPointValue];
            if (offset.y >= 0) {
                _restore = NO;
            }

            if (offset.y < 0 && !_restore) {
                _restore = YES;
                [self collectionView:self.collectionView header:nil didTapLoadEarlierMessages:nil];
            }

        }
    }
}

- (NSInteger)messageFunctionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    return 2;
}

- (void)messageFunctionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath categoryImageView:(UIImageView *)categoryImageView categoryLabel:(UILabel *)categoryLabel {
    switch (indexPath.row) {
    case 0: {
        categoryImageView.image = [UIImage jsq_categoryPhoto];
        categoryLabel.text = @"照片";
        break;
    }
    case 1: {
        categoryImageView.image = [UIImage jsq_categoryPicture];
        categoryLabel.text = @"拍照";
        break;
    }
    case 2: {
        categoryImageView.image = [UIImage jsq_categoryLocation];
        categoryLabel.text = @"位置";
        break;
    }
    case 3: {
        categoryImageView.image = [UIImage jsq_categoryRecommend];
        categoryLabel.text = @"推荐";
        break;
    }
    case 4: {
        categoryImageView.image = [UIImage jsq_categorySymptom];
        categoryLabel.text = @"人体症状";
        break;
    }
    case 5: {
        categoryImageView.image = [UIImage jsq_categoryHealthcare];
        categoryLabel.text = @"保健状态";
        break;
    }
    case 6: {
        categoryImageView.image = [UIImage jsq_categoryHealthy];
        categoryLabel.text = @"健康服务";
        break;
    }
    default:
        break;
    }
}

- (void)messageFunctionViewCategoryType:(NSInteger)item {
    switch (item) {
    case 0: {

        ALAuthorizationStatus author = [ALAssetsLibrary authorizationStatus];

        switch (author) {
        case ALAuthorizationStatusNotDetermined:
        case ALAuthorizationStatusAuthorized: {

            [self loadAssets];
            break;
        }
        case ALAuthorizationStatusRestricted:
        case ALAuthorizationStatusDenied: {
            NSString *message = @"如欲查看相册，请至设定->隐私->照片，开启本程序的照片服务功能";
            UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"无法访问相册" message:message delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil];
            [alertView show];
            break;
        }
        default: {
            break;
        }
        }


        break;
    }
    case 1: {
        AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];

        switch (authStatus) {
        case AVAuthorizationStatusNotDetermined:
        case AVAuthorizationStatusAuthorized: {
            if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
                UIImagePickerController *pickerController = [[UIImagePickerController alloc] init];
                pickerController.delegate = self;
                pickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
                [self presentViewController:pickerController animated:YES completion:^{

                        }];

            }
            break;
        }
        case AVAuthorizationStatusRestricted:
        case AVAuthorizationStatusDenied: {
            NSString *message = @"如欲开启相机，请至设定->隐私->相机，开启本程序的相机服务功能";
            UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"无法访问相机" message:message delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil];
            [alertView show];
            break;
        }
        default: {
            break;
        }
        }


        break;
    }
    case 2: {

        JSQMapViewController *mapViewController = [[JSQMapViewController alloc] init];
        mapViewController.mapViewType = JSQMapViewTypeChoice;
        mapViewController.delegate = self;

        [self.navigationController pushViewController:mapViewController animated:YES];

        break;
    }
    default:
        break;
    }
    [self inputToolbarReset];
}

- (void)didSendMapLocation:(NSString *)title location:(CLLocation *)location {
    JSQMessageModel *messageModel = [self createBasicMessages];

    [self sendLocal:messageModel mapLocation:title location:location];
}

#pragma mark - Actions

- (void)closePressed:(UIBarButtonItem *)sender {
    [self.delegateModal didDismissJSQDemoViewController:self];
}

- (void)sendImages:(NSArray *)images {
    for (UIImage *image in images) {

        NSData *imageData = UIImagePNGRepresentation(image);

        NSString *imagePath = [JSQMessageTools imagePath:[JSQMessageTools getCurrentSystemDateSecond]];

        [imageData writeToFile:imagePath atomically:YES];

        JSQPhotoMediaItem *photoItem = [[JSQPhotoMediaItem alloc] initWithImage:image];
        photoItem.appliesMediaViewMaskAsOutgoing = YES;
        JSQMessageModel *messageModel = [self createBasicMessages];
        messageModel.messageType = MESSAGE_TYPE_IMAGE;
        messageModel.fileSize = [JSQMessageTools fileSizeWithByteString:imagePath];

        JSQMessage *photoMessage = [JSQMessage messageWithModel:messageModel withMessageMediaData:photoItem];
        [self.messageData.messages addObject:photoMessage];
    }

    [JSQSystemSoundPlayer jsq_playMessageSentSound];

    [self finishSendingMessageAnimated:YES];
}

- (void)sendVoice:(JSQMessageModel *)messageModel {
    JSQAudioMediaItem *audioMediaItem = [[JSQAudioMediaItem alloc] initWithFileURL:[NSURL URLWithString:[JSQMessageTools audioFilePath:messageModel.fileLocalPath]] complete:nil];

    audioMediaItem.appliesMediaViewMaskAsOutgoing = YES;

    JSQMessage *message = [JSQMessage messageWithModel:messageModel withMessageMediaData:audioMediaItem];

    [self.messageData.messages addObject:message];

    [JSQSystemSoundPlayer jsq_playMessageSentSound];

    [self finishSendingMessageAnimated:YES];
}

- (void)sendLocal:(JSQMessageModel *)messageModel mapLocation:(NSString *)title location:(CLLocation *)location {
    JSQLocationMediaItem *locationMediaItem = [[JSQLocationMediaItem alloc] init];
    __weak typeof(self) VC = self;
    [locationMediaItem setLocation:location withLocationTitle:title withCompletionHandler:^{
        __strong typeof(VC) SVC = VC;
        [SVC.collectionView reloadData];
    }];

    messageModel.messageType = MESSAGE_TYPE_LOCATION;
    JSQMessage *message = [JSQMessage messageWithModel:messageModel withMessageMediaData:locationMediaItem];


    [self.messageData.messages addObject:message];

    [JSQSystemSoundPlayer jsq_playMessageSentSound];

    [self finishSendingMessageAnimated:YES];
}

#pragma mark - JSQMessagesViewController method overrides

- (void)didPressSendButton:(UIButton *)button withMessageModel:(JSQMessageModel *)messageModel withMessageMediaData:(id<JSQMessageMediaData>)messageMediaData {
    /**
     *  Sending a message. Your implementation of this method should do *at least* the following:
     *
     *  1. Play sound (optional)
     *  2. Add new id<JSQMessageData> object to your data source
     *  3. Call `finishSendingMessage`
     */
    [JSQSystemSoundPlayer jsq_playMessageSentSound];

    JSQMessage *message = [JSQMessage messageWithModel:messageModel withMessageMediaData:messageMediaData];

    [self.messageData.messages addObject:message];

    [self finishSendingMessageAnimated:YES];
}

#pragma mark - JSQMessages CollectionView DataSource

- (id<JSQMessageData>)collectionView:(JSQMessagesCollectionView *)collectionView messageDataForItemAtIndexPath:(NSIndexPath *)indexPath {
    return [self.messageData.messages objectAtIndex:indexPath.item];
}

- (void)collectionView:(JSQMessagesCollectionView *)collectionView didDeleteMessageAtIndexPath:(NSIndexPath *)indexPath {
    [self.messageData.messages removeObjectAtIndex:indexPath.item];
}

- (UIFont *)messageBubbleFontAtMessageData:(id<JSQMessageData>)messageData atIndexPath:(NSIndexPath *)indexPath {
    switch ([messageData messageType]) {
    case MESSAGE_TYPE_GROUP_JOIN:
    case MESSAGE_TYPE_GROUP_LEAVE: {
        return [UIFont systemFontOfSize:12];
        break;
    }

    default: {
        return [UIFont systemFontOfSize:16];
        break;
    }
    }
}

- (MenuType)collectionViewMenu:(JSQMessagesCollectionView *)collectionView messageBubbleAtIndexPath:(NSIndexPath *)indexPath {
    JSQMessage *message = [self.messageData.messages objectAtIndex:indexPath.item];

    switch ([message messageType]) {
    case MESSAGE_TYPE_TEXT: {
        return (MenuTypeCollection | MenuTypeDelete | MenuTypeForward | MenuTypeCopy);
        break;
    }
    case MESSAGE_TYPE_IMAGE: {
        return (MenuTypeCollection | MenuTypeDelete | MenuTypeForward);
        break;
    }
    case MESSAGE_TYPE_VOICE: {
        return (MenuTypeDelete);
        break;
    }
    case MESSAGE_TYPE_LOCATION: {
        return (MenuTypeDelete);
        break;
    }
    default:
        break;
    }


    return MenuTypeNone;
}

- (id<JSQMessageBubbleImageDataSource>)collectionView:(JSQMessagesCollectionView *)collectionView messageBubbleImageDataForItemAtIndexPath:(NSIndexPath *)indexPath {
    /**
     *  You may return nil here if you do not want bubbles.
     *  In this case, you should set the background color of your collection view cell's textView.
     *
     *  Otherwise, return your previously created bubble image data objects.
     */

    JSQMessage *message = [self.messageData.messages objectAtIndex:indexPath.item];

    if ([message.senderId isEqualToString:self.senderId]) {
        return self.messageData.outgoingBubbleImageData;
    }

    return self.messageData.incomingBubbleImageData;
}

- (id<JSQMessageAvatarImageDataSource>)collectionView:(JSQMessagesCollectionView *)collectionView avatarImageDataForItemAtIndexPath:(NSIndexPath *)indexPath {
    /**
     *  Return `nil` here if you do not want avatars.
     *  If you do return `nil`, be sure to do the following in `viewDidLoad`:
     *
     *  self.collectionView.collectionViewLayout.incomingAvatarViewSize = CGSizeZero;
     *  self.collectionView.collectionViewLayout.outgoingAvatarViewSize = CGSizeZero;
     *
     *  It is possible to have only outgoing avatars or only incoming avatars, too.
     */

    /**
     *  Return your previously created avatar image data objects.
     *
     *  Note: these the avatars will be sized according to these values:
     *
     *  self.collectionView.collectionViewLayout.incomingAvatarViewSize
     *  self.collectionView.collectionViewLayout.outgoingAvatarViewSize
     *
     *  Override the defaults in `viewDidLoad`
     */
    JSQMessage *message = [self.messageData.messages objectAtIndex:indexPath.item];


    return [self.messageData.avatars objectForKey:message.senderId];
}

- (NSAttributedString *)collectionView:(JSQMessagesCollectionView *)collectionView attributedTextForCellTopLabelAtIndexPath:(NSIndexPath *)indexPath {

    if (indexPath.item) {
        JSQMessage *message = [self.messageData.messages objectAtIndex:indexPath.item];
        JSQMessage *nextMessage = [self.messageData.messages objectAtIndex:indexPath.item - 1];
        if ([JSQMessageTools timeDifference:nextMessage.date date:message.date interval:300]) {
            return [[JSQMessagesTimestampFormatter sharedFormatter] attributedTimestampForDate:message.date];
        } else {
            return nil;
        }
    } else {
        JSQMessage *message = [self.messageData.messages objectAtIndex:indexPath.item];
        return [[JSQMessagesTimestampFormatter sharedFormatter] attributedTimestampForDate:message.date];
    }

}

- (NSAttributedString *)collectionView:(JSQMessagesCollectionView *)collectionView attributedTextForMessageBubbleTopLabelAtIndexPath:(NSIndexPath *)indexPath {
    JSQMessage *message = [self.messageData.messages objectAtIndex:indexPath.item];

    /**
     *  iOS7-style sender name labels
     */
    if ([message.senderId isEqualToString:self.senderId]) {
        return nil;
    }

    if (indexPath.item - 1 > 0) {
        JSQMessage *previousMessage = [self.messageData.messages objectAtIndex:indexPath.item - 1];
        if ([[previousMessage senderId] isEqualToString:message.senderId]) {
            return nil;
        }
    }

    /**
     *  Don't specify attributes to use the defaults.
     */
    return [[NSAttributedString alloc] initWithString:message.senderDisplayName];
}

- (NSAttributedString *)collectionView:(JSQMessagesCollectionView *)collectionView attributedTextForCellBottomLabelAtIndexPath:(NSIndexPath *)indexPath {
    return nil;
}

#pragma mark - UICollectionView DataSource

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    return [self.messageData.messages count];
}

- (UICollectionViewCell *)collectionView:(JSQMessagesCollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    /**
     *  Override point for customizing cells
     */
    JSQMessagesCollectionViewCell *cell = (JSQMessagesCollectionViewCell *)[super collectionView:collectionView cellForItemAtIndexPath:indexPath];

    /**
     *  Configure almost *anything* on the cell
     *
     *  Text colors, label text, label colors, etc.
     *
     *
     *  DO NOT set `cell.textView.font` !
     *  Instead, you need to set `self.collectionView.collectionViewLayout.messageBubbleFont` to the font you want in `viewDidLoad`
     *
     *
     *  DO NOT manipulate cell layout information!
     *  Instead, override the properties you want on `self.collectionView.collectionViewLayout` from `viewDidLoad`
     */

    JSQMessage *msg = [self.messageData.messages objectAtIndex:indexPath.item];

    if (!msg.isMediaMessage) {

        if ([msg.senderId isEqualToString:self.senderId]) {
            cell.textView.textColor = [UIColor whiteColor];
        } else {
            cell.textView.textColor = [UIColor blackColor];
        }

        cell.textView.linkTextAttributes = @{ NSForegroundColorAttributeName : cell.textView.textColor,
                                              NSUnderlineStyleAttributeName : @(NSUnderlineStyleSingle | NSUnderlinePatternSolid) };
    }

    switch (msg.messageStatus) {
    case MESSAGE_STATE_SENDING:
    case MESSAGE_STATE_DOWNLOADING: {
        cell.progressActivityIndicatorView.hidden = NO;
        [cell.progressActivityIndicatorView startAnimating];
        break;
    }
    case MESSAGE_STATE_NOTSEND:
    case MESSAGE_STATE_RECEIVED:
    case MESSAGE_STATE_DOWNLOADED:
    case MESSAGE_STATE_ARRIVED:
    case MESSAGE_STATE_READ:
    case MESSAGE_STATE_SENT:
    case MESSAGE_STATE_DOWNLOAD_FAIL:
    case MESSAGE_STATE_SEND_FAIL:
    case MESSAGE_STATE_UNREAD: {
        cell.progressActivityIndicatorView.hidden = YES;
        [cell.progressActivityIndicatorView stopAnimating];
        break;
    }
    default:
        break;
    }

    return cell;
}

#pragma mark - UICollectionView Delegate

#pragma mark - Custom menu items

- (BOOL)collectionView:(UICollectionView *)collectionView canPerformAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender {
    return [super collectionView:collectionView canPerformAction:(SEL)action forItemAtIndexPath:indexPath withSender:(id)sender];
}

- (void)collectionView:(UICollectionView *)collectionView performAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender {
    [super collectionView:collectionView performAction:action forItemAtIndexPath:indexPath withSender:sender];
}

- (void)customCopy:(id<JSQMessageData>)messageData {

}

- (void)customDelete:(id<JSQMessageData>)messageData forItemAtIndexPath:(NSIndexPath *)indexPath {

}

- (void)collection:(id<JSQMessageData>)messageData forItemAtIndexPath:(NSIndexPath *)indexPath {

}

- (void)forward:(id<JSQMessageData>)messageData forItemAtIndexPath:(NSIndexPath *)indexPath {

}

- (void)showImageViewMoreOperation:(UIViewController *)viewController showImage:(UIImage *)image {

}

#pragma mark - JSQMessages collection view flow layout delegate

#pragma mark - Adjusting cell label heights

- (CGFloat)collectionView:(JSQMessagesCollectionView *)collectionView layout:(JSQMessagesCollectionViewFlowLayout *)collectionViewLayout heightForCellTopLabelAtIndexPath:(NSIndexPath *)indexPath {
    /**
     *  Each label in a cell has a `height` delegate method that corresponds to its text dataSource method
     */

    /**
     *  This logic should be consistent with what you return from `attributedTextForCellTopLabelAtIndexPath:`
     *  The other label height delegate methods should follow similarly
     *
     *  Show a timestamp for every 3rd message
     */

    if (indexPath.item) {
        JSQMessage *message = [self.messageData.messages objectAtIndex:indexPath.item];
        JSQMessage *nextMessage = [self.messageData.messages objectAtIndex:indexPath.item - 1];
        if ([JSQMessageTools timeDifference:nextMessage.date date:message.date interval:300]) {
            return kJSQMessagesCollectionViewCellLabelHeightDefault;
        } else {
            return 0.0f;
        }
    } else {
        return kJSQMessagesCollectionViewCellLabelHeightDefault;
    }

}

- (CGFloat)collectionView:(JSQMessagesCollectionView *)collectionView layout:(JSQMessagesCollectionViewFlowLayout *)collectionViewLayout heightForMessageBubbleTopLabelAtIndexPath:(NSIndexPath *)indexPath {
    /**
     *  iOS7-style sender name labels
     */
    JSQMessage *currentMessage = [self.messageData.messages objectAtIndex:indexPath.item];
    if ([[currentMessage senderId] isEqualToString:self.senderId]) {
        return 0.0f;
    }

    if (indexPath.item - 1 > 0) {
        JSQMessage *previousMessage = [self.messageData.messages objectAtIndex:indexPath.item - 1];
        if ([[previousMessage senderId] isEqualToString:[currentMessage senderId]]) {
            return 0.0f;
        }
    }

    return kJSQMessagesCollectionViewCellLabelHeightDefault;
}

- (CGFloat)collectionView:(JSQMessagesCollectionView *)collectionView layout:(JSQMessagesCollectionViewFlowLayout *)collectionViewLayout heightForCellBottomLabelAtIndexPath:(NSIndexPath *)indexPath {
    return 0.0f;
}

#pragma mark - Responding to collection view tap events

- (void)collectionView:(JSQMessagesCollectionView *)collectionView header:(JSQMessagesLoadEarlierHeaderView *)headerView didTapLoadEarlierMessages:(UIButton *)sender {
    NSLog(@"Load earlier messages!");
}

- (void)collectionView:(JSQMessagesCollectionView *)collectionView didTapAvatarImageView:(UIImageView *)avatarImageView atIndexPath:(NSIndexPath *)indexPath {
    [self inputToolbarReset];
    NSLog(@"Tapped avatar!");
}

- (void)collectionView:(JSQMessagesCollectionView *)collectionView didTapMessageBubbleAtIndexPath:(NSIndexPath *)indexPath {
    id<JSQMessageData> messageData = [collectionView.dataSource collectionView:collectionView messageDataForItemAtIndexPath:indexPath];

    switch ([messageData messageType]) {
    case MESSAGE_TYPE_TEXT: {

        NSLog(@"Tapped MESSAGE_TYPE_TEXT message bubble!");
        break;
    }
    case MESSAGE_TYPE_IMAGE: {
        NSLog(@"Tapped MESSAGE_TYPE_IMAGE message bubble!");

        NSMutableArray *imageArray = [NSMutableArray array];
        NSInteger index = 0;
        for (JSQMessage *message in _messageData.messages) {
            if ([[message mediaData] isKindOfClass:[JSQPhotoMediaItem class]]) {
                [imageArray addObject:message];
                if ([message mediaData] == [messageData media]) {
                    index = imageArray.count - 1;
                }
            }
        }
        JSQShowImageViewController *showImageViewController = [[JSQShowImageViewController alloc] initWithSourceData:imageArray withIndex:index];
        showImageViewController.delegate = self;

        [self presentViewController:showImageViewController animated:YES completion:nil];
        break;
    }
    case MESSAGE_TYPE_VOICE: {
        NSLog(@"Tapped MESSAGE_TYPE_VOICE message bubble!");

        JSQMessagesCollectionViewVoiceCell *collectionCell = (JSQMessagesCollectionViewVoiceCell *)[self.collectionView cellForItemAtIndexPath:indexPath];

        NSFileManager *fileManager = [NSFileManager defaultManager];
        NSString *filePath = [messageData fileLocalPath];
        if ([fileManager fileExistsAtPath:filePath]) {
            [self.audioAnimation playFilePath:[NSURL fileURLWithPath:filePath] animation:collectionCell];
        }
        break;
    }
    case MESSAGE_TYPE_LOCATION: {
        NSLog(@"Tapped MESSAGE_TYPE_LOCATION message bubble!");

        JSQLocationMediaItem *locationMediaItem = (JSQLocationMediaItem *)[messageData media];

        JSQMapViewController *mapViewController = [[JSQMapViewController alloc] init];
        mapViewController.mapViewType = JSQMapViewTypeShow;

        JSQMapLocation *mapLocation = [[JSQMapLocation alloc] init];
        mapLocation.addressTitle = locationMediaItem.locationTitle;
        mapLocation.coordinate = locationMediaItem.coordinate;
        mapLocation.location = locationMediaItem.location;

        mapViewController.annotaion = mapLocation;

        [self.navigationController pushViewController:mapViewController animated:YES];
        break;
    }
    case MESSAGE_TYPE_SOS: {
        NSLog(@"Tapped MESSAGE_TYPE_SOS message bubble!");
        break;
    }
    default:
        break;
    }
}

- (void)collectionView:(JSQMessagesCollectionView *)collectionView didTapCellAtIndexPath:(NSIndexPath *)indexPath touchLocation:(CGPoint)touchLocation {
    [self inputToolbarReset];
    NSLog(@"Tapped cell at %@!", NSStringFromCGPoint(touchLocation));
}

#pragma mark - JSQMessagesComposerTextViewPasteDelegate methods


- (BOOL)composerTextView:(JSQMessagesComposerTextView *)textView shouldPasteWithSender:(id)sender {
    if ([UIPasteboard generalPasteboard].image) {
        // If there's an image in the pasteboard, construct a media item with that image and `send` it.
        JSQPhotoMediaItem *item = [[JSQPhotoMediaItem alloc] initWithImage:[UIPasteboard generalPasteboard].image];

        JSQMessageModel *messageModel = [[JSQMessageModel alloc] init];
        messageModel.date = [NSDate date];
        messageModel.senderId = self.senderId;
        messageModel.senderDisplayName = self.senderDisplayName;

        [self.messageData.messages addObject:[JSQMessage messageWithModel:messageModel withMessageMediaData:item]];
        [self finishSendingMessage];
        return NO;
    }
    return YES;
}

#pragma mark - Load Assets

- (void)showPhotoBrowser {
    NSMutableArray *photos = [NSMutableArray array];
    NSMutableArray *thumbs = [NSMutableArray array];
    @synchronized(_assets) {
        NSMutableArray *copy = [_assets copy];
        if (NSClassFromString(@"PHAsset")) {
            // Photos library
            UIScreen *screen = [UIScreen mainScreen];
            CGFloat scale = screen.scale;
            // Sizing is very rough... more thought required in a real implementation
            CGFloat imageSize = MAX(screen.bounds.size.width, screen.bounds.size.height) * 1.5;
            CGSize imageTargetSize = CGSizeMake(imageSize * scale, imageSize * scale);
            CGSize thumbTargetSize = CGSizeMake(imageSize / 3.0 * scale, imageSize / 3.0 * scale);
            for (PHAsset *asset in copy) {
                [photos addObject:[MWPhoto photoWithAsset:asset targetSize:imageTargetSize]];
                [thumbs addObject:[MWPhoto photoWithAsset:asset targetSize:thumbTargetSize]];
            }
        } else {
            // Assets library
            for (ALAsset *asset in copy) {
                MWPhoto *photo = [MWPhoto photoWithURL:asset.defaultRepresentation.url];
                [photos addObject:photo];
                MWPhoto *thumb = [MWPhoto photoWithImage:[UIImage imageWithCGImage:asset.thumbnail]];
                [thumbs addObject:thumb];
            }
        }
    }

    self.photos = photos;
    self.thumbs = thumbs;

    _selections = [NSMutableArray array];
    for (int i = 0; i < photos.count; i++) {
        [_selections addObject:[NSNumber numberWithBool:NO]];
    }

    MWPhotoBrowser *photoBrowser = [[MWPhotoBrowser alloc] initWithDelegate:self];
    photoBrowser.displayActionButton = NO;
    photoBrowser.displayNavArrows = NO;
    photoBrowser.displaySelectionButtons = YES;
    photoBrowser.alwaysShowControls = YES;
    photoBrowser.zoomPhotosToFill = YES;
    photoBrowser.enableGrid = YES;
    photoBrowser.startOnGrid = YES;
    photoBrowser.enableSwipeToDismiss = NO;
    photoBrowser.autoPlayOnAppear = NO;

    _photoBrowser = photoBrowser;

    UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:photoBrowser];
    [self presentViewController:navigationController animated:YES completion:nil];
}

- (void)loadAssets {
    if (NSClassFromString(@"PHAsset")) {

        // Check library permissions
        PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus];
        if (status == PHAuthorizationStatusNotDetermined) {
            [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
                if (status == PHAuthorizationStatusAuthorized) {
                    __weak typeof(self) VC = self;
                    [self performLoadAssets:^{
                        [VC showPhotoBrowser];
                    }];
                } else {
                    NSString *message = @"如欲查看相册，请至设定->隐私->照片，开启本程序的照片服务功能";
                    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"无法访问相册" message:message delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil];
                    [alertView show];
                }
            }];
        } else if (status == PHAuthorizationStatusAuthorized) {
            __weak typeof(self) VC = self;
            [self performLoadAssets:^{
                [VC showPhotoBrowser];
            }];
        } else {
            NSString *message = @"如欲查看相册，请至设定->隐私->照片，开启本程序的照片服务功能";
            UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"无法访问相册" message:message delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil];
            [alertView show];
        }

    } else {

        ALAuthorizationStatus author = [ALAssetsLibrary authorizationStatus];

        switch (author) {
        case ALAuthorizationStatusNotDetermined:
        case ALAuthorizationStatusAuthorized: {

            // Assets library
            __weak typeof(self) VC = self;
            [self performLoadAssets:^{
                    [VC showPhotoBrowser];
                }];
            break;
        }
        case ALAuthorizationStatusRestricted:
        case ALAuthorizationStatusDenied: {
            NSString *message = @"如欲查看相册，请至设定->隐私->照片，开启本程序的照片服务功能";
            UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"无法访问相册" message:message delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil];
            [alertView show];
            break;
        }
        default: {
            break;
        }
        }
    }
}

- (void)performLoadAssets:(void (^)(void))complete {
    
    if (_assets) {
        [_assets removeAllObjects];
    } else {
        _assets = [NSMutableArray array];
    }
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
    // Load
    if (NSClassFromString(@"PHAsset")) {

        // Photos library iOS >= 8
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            PHFetchOptions *options = [PHFetchOptions new];
            options.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:NO]];
            PHFetchResult *fetchResults = [PHAsset fetchAssetsWithOptions:options];
            [fetchResults enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
                [_assets addObject:obj];

                if (fetchResults.count == idx + 1) {
                    dispatch_semaphore_signal(semaphore);
                }
            }];
        });

    } else {

        // Assets Library iOS < 8
        _ALAssetsLibrary = [[ALAssetsLibrary alloc] init];

        // Run in the background as it takes a while to get all assets from the library
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

            NSMutableArray *assetGroups = [[NSMutableArray alloc] init];
            NSMutableArray *assetURLDictionaries = [[NSMutableArray alloc] init];

            // Process!
            [_ALAssetsLibrary enumerateGroupsWithTypes:ALAssetsGroupAll
                                            usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
                                                if (group != nil) {
                                                    [group enumerateAssetsWithOptions:NSEnumerationReverse usingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) {
                                                        if (result != nil) {
                                                            NSString *assetType = [result valueForProperty:ALAssetPropertyType];
                                                            if ([assetType isEqualToString:ALAssetTypePhoto]) {
                                                                [assetURLDictionaries addObject:[result valueForProperty:ALAssetPropertyURLs]];
                                                                NSURL *url = result.defaultRepresentation.url;
                                                                [_ALAssetsLibrary assetForURL:url resultBlock:^(ALAsset *asset) {
                                                                    if (asset) {
                                                                        @synchronized(_assets) {
                                                                            [_assets addObject:asset];
                                                                        }
                                                                    }
                                                                }
                                                                                 failureBlock:^(NSError *error){
                                                                                     NSLog(@"operation was not successfull!");
                                                                                 }];
                                                                
                                                            }
                                                        }
                                                        
                                                    }];
                                                    [assetGroups addObject:group];
                                                }else {
                                                    dispatch_semaphore_signal(semaphore);
                                                }
                                                
                                            } failureBlock:^(NSError *error) {
                NSLog(@"There is an error");
            }];

        });

    }

    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

    if (complete) {
        complete();
    }
}

#pragma mark - MWPhotoBrowserDelegate

- (NSUInteger)numberOfPhotosInPhotoBrowser:(MWPhotoBrowser *)photoBrowser {
    return _photos.count;
}

- (id <MWPhoto>)photoBrowser:(MWPhotoBrowser *)photoBrowser photoAtIndex:(NSUInteger)index {
    if (index < _photos.count)
        return [_photos objectAtIndex:index];
    return nil;
}

- (id <MWPhoto>)photoBrowser:(MWPhotoBrowser *)photoBrowser thumbPhotoAtIndex:(NSUInteger)index {
    if (index < _thumbs.count)
        return [_thumbs objectAtIndex:index];
    return nil;
}

- (void)photoBrowser:(MWPhotoBrowser *)photoBrowser didDisplayPhotoAtIndex:(NSUInteger)index {
    NSLog(@"Did start viewing photo at index %lu", (unsigned long)index);
}

- (BOOL)photoBrowser:(MWPhotoBrowser *)photoBrowser isPhotoSelectedAtIndex:(NSUInteger)index {
    if (index < _selections.count)
        return [[_selections objectAtIndex:index] boolValue];
    return NO;
}

- (void)photoBrowser:(MWPhotoBrowser *)photoBrowser photoAtIndex:(NSUInteger)index selectedChanged:(BOOL)selected {
    [_selections replaceObjectAtIndex:index withObject:[NSNumber numberWithBool:selected]];
    NSLog(@"Photo at index %lu selected %@", (unsigned long)index, selected ? @"YES" : @"NO");
}

- (void)photoBrowserDidFinishModalPresentation:(MWPhotoBrowser *)photoBrowser {
    // If we subscribe to this method we must dismiss the view controller ourselves

    NSMutableArray *imageArray = [NSMutableArray array];

    if (NSClassFromString(@"PHAsset")) {
        PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
        options.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;


        for (NSInteger i = 0; i < _selections.count; i++) {
            __block NSNumber *number = [_selections objectAtIndex:i];
            if ([number boolValue]) {
                PHAsset *asset = [_assets objectAtIndex:i];
                [imageArray addObject:asset];
                number = [NSNumber numberWithBool:NO];
            }
        }

        if (!imageArray.count) {
            [self dismissViewControllerAnimated:YES completion:nil];
            return;
        }

        NSMutableArray *assetArray = [NSMutableArray array];
        for (PHAsset *asset in imageArray) {
            __weak typeof(self) VC = self;
            [[PHImageManager defaultManager] requestImageForAsset:asset targetSize:[UIScreen mainScreen].bounds.size contentMode:PHImageContentModeAspectFit options:options resultHandler:^(UIImage *result, NSDictionary *info) {

                UIImage *image = [JSQMessageTools scaleToSize:result size:CGSizeMake(480, 640)];
                [assetArray addObject:image];

                if (assetArray.count == imageArray.count) {
                    [VC sendImages:assetArray];
                    [VC dismissViewControllerAnimated:YES completion:nil];
                }
            }];
        }
    } else {
        for (NSInteger i = 0; i < _selections.count; i++) {
            NSNumber *number = [_selections objectAtIndex:i];
            if ([number boolValue]) {
                ALAsset *asset = [_assets objectAtIndex:i];
                UIImage *image = [UIImage imageWithCGImage:asset.thumbnail];
                image = [JSQMessageTools scaleToSize:image size:CGSizeMake(480, 640)];
                [imageArray addObject:image];

                number = [NSNumber numberWithBool:NO];
            }
        }
        [self sendImages:imageArray];

        [self dismissViewControllerAnimated:YES completion:nil];
    }
}

#pragma mark -
#pragma mark UIImagePickerControllerDelegate

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
    [picker dismissViewControllerAnimated:YES completion:^{

    }];

    if ([[info objectForKey:UIImagePickerControllerMediaType] isEqualToString:@"public.image"]) {
        UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];

        image = [JSQMessageTools scaleToSize:image size:CGSizeMake(480, 640)];

        [self sendImages:@[image]];
    }
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end
